use std::collections::HashMap;

use crate::data::{DatasetOwner, RowsetOwner};

use super::{metadata::MetadataBase, Metadata};

#[derive(Debug, Clone)]
// #[derive( Serialize, )]
// #[serde(crate = "self::serde")]
// #[serde(rename_all = "camelCase")]
pub struct DoMetadata {
    pub(crate) base: MetadataBase,
    // 主键
    pub(crate) sys_keys: Option<DatasetOwner>,
    // 列定义
    pub(crate) sys_obj_cols: Option<DatasetOwner>,
    // 外键及其关联的DoMetadata ID
    // TODO: 关联的DoMetadata ID未来可能替换为DoMetadata引用
    pub(crate) fkey_metadata_map: HashMap<String, String>,
    // 索引
    pub(crate) sys_indexs: Option<DatasetOwner>,
    // 扩展属性
    pub(crate) sys_obj_val: HashMap<String, String>,
    // 该DoMetadata所属的DctMetadata ID
    // TODO: 所属的DctMetadata ID未来可能替换为DctMetadata引用
    pub(crate) dct_metadata_id: Option<String>,
    // 该DoMetadata所属的FctMetadata ID
    // TODO: 所属的FctMetadata ID未来可能替换为FctMetadata引用
    pub(crate) fct_metadata_id: Option<String>,
    // TODO:
    // pub(crate) io_metadata: Option<IoMetadata>/Option<String>;
    // Deprecated:
    // pub(crate) ref_do_id: Option<String>,
}

impl Into<Metadata> for DoMetadata {
    fn into(self) -> Metadata {
        Metadata::Do(self)
    }
}

impl DoMetadata {
    pub fn new(dct_id: &str, rowset: RowsetOwner) -> Self {
        Self {
            base: MetadataBase::new(dct_id, rowset),
            sys_keys: None,
            sys_obj_cols: None,
            fkey_metadata_map: Default::default(),
            sys_indexs: None,
            sys_obj_val: Default::default(),
            dct_metadata_id: None,
            fct_metadata_id: None,
            // ref_do_id: None,
        }
    }
}

impl DoMetadata {
    pub fn get_object_id(&self) -> &str {
        &self.base.object_id
    }

    pub fn get_keys(&self) -> Option<&DatasetOwner> {
        self.sys_keys.as_ref()
    }

    pub fn set_keys(&mut self, dataset: DatasetOwner) {
        self.sys_keys = Some(dataset);
    }

    pub fn get_columns(&self) -> Option<&DatasetOwner> {
        self.sys_obj_cols.as_ref()
    }

    pub fn set_columns(&mut self, dataset: DatasetOwner) {
        self.sys_obj_cols = Some(dataset);
    }

    pub fn add_fkey_metadata(&mut self, fkey: String, object_id: String) {
        self.fkey_metadata_map.insert(fkey, object_id);
    }

    pub fn get_fkey_metadatas(&self) -> Vec<String> {
        self.fkey_metadata_map
            .values()
            .map(|x| x.to_owned())
            .collect::<Vec<_>>()
    }

    pub fn get_indexs(&self) -> Option<&DatasetOwner> {
        self.sys_indexs.as_ref()
    }

    pub fn set_indexs(&mut self, dataset: DatasetOwner) {
        self.sys_indexs = Some(dataset);
    }

    pub fn add_sys_obj_val(&mut self, key: &str, value: &str) {
        self.sys_obj_val.insert(key.to_owned(), value.to_owned());
    }
}

impl DoMetadata {
    pub fn set_dct_metadata(&mut self, dct_metadata_id: &str) {
        self.dct_metadata_id = Some(dct_metadata_id.to_owned())
    }

    pub fn set_fct_metadata(&mut self, fct_metadata_id: &str) {
        self.fct_metadata_id = Some(fct_metadata_id.to_owned())
    }
}

// Deprecated
// impl DoMetadata {
//     pub fn set_ref_do_id(&mut self, ref_do_id: String) {
//         self.ref_do_id = Some(ref_do_id);
//     }
//     pub fn get_ref_do_id(&self) -> Option<&String> {
//         self.ref_do_id.as_ref()
//     }
// }
